// -*- coding: utf-8 -*-
/*
author: zengbin93
email: zeng_bin8888@163.com
create_dt: 2022/12/16 19:37
describe: 飞书应用API接口封装
*/

pub mod base;
pub mod bi_table;
pub mod im;
pub mod spreed_sheets;

pub use base::{request, FeishuApiBase};
pub use bi_table::BiTable;
pub use im::IM;
pub use spreed_sheets::{SpreadSheets, SingleSheet};

use log;
use serde_json::Value;
use std::collections::HashMap;

/// 使用自定义机器人推送文本消息到飞书群聊
/// 
/// 如何在群组中使用机器人:
/// - https://www.feishu.cn/hc/zh-CN/articles/360024984973
/// - https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN
/// 
/// # Arguments
/// * `text` - 文本内容
/// * `key` - 机器人的key
pub async fn push_text(text: &str, key: &str) -> Result<(), Box<dyn std::error::Error>> {
    let api_send = format!("https://open.feishu.cn/open-apis/bot/v2/hook/{}", key);
    let data = serde_json::json!({
        "msg_type": "text",
        "content": {
            "text": text
        }
    });
    
    let client = reqwest::Client::new();
    let response = client.post(&api_send)
        .json(&data)
        .send()
        .await?;
    
    let response_json: Value = response.json().await?;
    if response_json["StatusMessage"] == "success" {
        Ok(())
    } else {
        Err(format!("推送消息失败: {:?}", response_json).into())
    }
}

/// 使用自定义机器人推送卡片消息到飞书群聊
/// 
/// 如何在群组中使用机器人:
/// - https://www.feishu.cn/hc/zh-CN/articles/360024984973
/// - https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN
/// 
/// # Arguments
/// * `card` - 卡片内容
/// * `key` - 机器人的key
pub async fn push_card(card: &Value, key: &str) -> Result<(), Box<dyn std::error::Error>> {
    let api_send = format!("https://open.feishu.cn/open-apis/bot/v2/hook/{}", key);
    let data = serde_json::json!({
        "msg_type": "interactive",
        "card": card
    });
    
    let client = reqwest::Client::new();
    let response = client.post(&api_send)
        .json(&data)
        .send()
        .await?;
    
    let response_json: Value = response.json().await?;
    if response_json["StatusMessage"] == "success" {
        Ok(())
    } else {
        logger::error!("推送消息失败: {:?}", response_json);
        Err("推送消息失败".into())
    }
}

/// 读取飞书电子表格
/// 
/// id和token的获取，参考：https://open.feishu.cn/document/ukTMukTMukTM/uATMzUjLwEzM14CMxMTN/overview
/// 
/// # Arguments
/// * `spread_sheet_token` - 电子表格token
/// * `sheet_id` - 电子表格中指定 sheet 的 id
/// * `app_id` - 飞书APP的app_id
/// * `app_secret` - 飞书APP的app_secret
pub async fn read_feishu_sheet(
    spread_sheet_token: &str, 
    sheet_id: Option<&str>,
    app_id: &str,
    app_secret: &str
) -> Result<Vec<HashMap<String, String>>, Box<dyn std::error::Error>> {
    let ss = SpreadSheets::new(app_id, app_secret);
    
    let sheet_id = if let Some(id) = sheet_id {
        id.to_string()
    } else {
        let res = ss.get_sheets(spread_sheet_token).await?;
        res["data"]["sheets"][0]["sheet_id"].as_str().unwrap().to_string()
    };
    
    let df = ss.read_table(spread_sheet_token, &sheet_id).await?;
    Ok(df)
}

/// 根据手机号获取飞书用户id
/// 
/// 飞书接口文档：https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/batch_get_id
/// 
/// # Arguments
/// * `mobiles` - 手机号列表
/// * `app_id` - 飞书APP的app_id
/// * `app_secret` - 飞书APP的app_secret
pub async fn get_feishu_members_by_mobiles(
    mobiles: &[String],
    app_id: &str,
    app_secret: &str
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let fim = IM::new(app_id, app_secret);
    let res = fim.get_user_id(mobiles).await?;
    
    let user_list = res["data"]["user_list"].as_array().unwrap();
    let user_ids: Vec<String> = user_list
        .iter()
        .map(|x| x["user_id"].as_str().unwrap().to_string())
        .collect();
    
    Ok(user_ids)
}

/// 使用飞书APP批量推送消息
/// 
/// API介绍：https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/create
/// 请求体构建: https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/im-v1/message/create_json
/// 
/// # Arguments
/// * `msg` - 消息内容
/// * `msg_type` - 消息类型，支持：text, image, file, card
/// * `receive_id_type` - 接收者是用户还是群聊 open_id / user_id / union_id / email / chat_id
/// * `members` - 需要通知的飞书APP的成员列表
/// * `app_id` - 飞书APP的app_id
/// * `app_secret` - 飞书APP的app_secret
pub async fn push_message(
    msg: &str,
    msg_type: &str,
    receive_id_type: &str,
    members: &[String],
    app_id: &str,
    app_secret: &str
) -> Result<(), Box<dyn std::error::Error>> {
    let fim = IM::new(app_id, app_secret);
    
    for member in members {
        match msg_type {
            "text" => fim.send_text(msg, member, receive_id_type).await?,
            "image" => fim.send_image(msg, member, receive_id_type).await?,
            "file" => fim.send_file(msg, member, receive_id_type).await?,
            "card" => fim.send_card(msg, member, receive_id_type).await?,
            _ => {
                logger::error!("不支持的消息类型：{}", msg_type);
                return Err("不支持的消息类型".into());
            }
        }
    }
    
    Ok(())
}

/// 使用飞书机器人更新电子表格
/// 
/// 获取 spreadsheet_token - https://open.feishu.cn/document/server-docs/docs/faq  第7节
/// 获取 sheet_id - https://open.feishu.cn/document/server-docs/docs/sheets-v3/spreadsheet-sheet/query?appId=cli_a3077015cc39500e
/// 
/// # Arguments
/// * `data` - 数据内容
/// * `spreadsheet_token` - 表格对应的token，url获取
/// * `sheet_id` - 工作表的id
/// * `app_id` - 飞书APP的app_id
/// * `app_secret` - 飞书APP的app_secret
pub async fn update_spreadsheet(
    data: &[HashMap<String, String>],
    spreadsheet_token: &str,
    sheet_id: &str,
    app_id: &str,
    app_secret: &str
) -> Result<i32, Box<dyn std::error::Error>> {
    let fsf = SpreadSheets::new(app_id, app_secret);
    
    if data.is_empty() {
        return Ok(0);
    }
    
    let headers: Vec<String> = data[0].keys().cloned().collect();
    let values: Vec<Vec<String>> = data
        .iter()
        .map(|row| headers.iter().map(|key| row.get(key).unwrap_or(&String::new()).clone()).collect())
        .collect();
    
    let update_data = serde_json::json!({
        "valueRanges": [
            {
                "range": format!("{}!A1:Z1", sheet_id),
                "values": [headers]
            },
            {
                "range": format!("{}!A2:Z5000", sheet_id),
                "values": values
            }
        ]
    });
    
    match fsf.delete_values(spreadsheet_token, sheet_id).await {
        Ok(_) => {
            match fsf.update_values(spreadsheet_token, &update_data).await {
                Ok(b) => {
                    if b["code"] == 0 {
                        logger::success!("更新飞书表格成功");
                        Ok(1)
                    } else {
                        logger::error!("{:?}", b);
                        Ok(0)
                    }
                }
                Err(e) => {
                    logger::exception!("更新飞书表格失败: {}", e);
                    Ok(0)
                }
            }
        }
        Err(e) => {
            logger::exception!("删除表格数据失败: {}", e);
            Ok(0)
        }
    }
} 